package at.codebase.web.util.json;

import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONObject;


import at.codebase.web.util.json.JsonKeys;
import at.codebase.core.FeedbackData;
import at.codebase.core.search.ItemSearchResult;
import at.codebase.core.search.ItemSearchResultInfo;
import at.codebase.db.entities.EItem;
import at.codebase.db.entities.EItemFeedback;
import at.codebase.db.entities.EUser;
import at.codebase.db.entities.EUser.EGoogleUserData;
import at.codebase.db.entities.GeoPoint;


/**
 * @author Daniel Marth <danielmarth@gmx.at>
 */
public class JsonEncoder {

	@SuppressWarnings("unchecked")
	public static JSONObject encodeItem(final EItem item) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.ITEM);
		obj.put(JsonKeys.ITEM_ID, item.getId());
		obj.put(JsonKeys.TITLE, item.getTitle());
		obj.put(JsonKeys.DESCRIPTION, item.getDescription());
		obj.put(JsonKeys.ACTIVE, new Boolean(item.isActive()));
		obj.put(JsonKeys.DELETED, new Boolean(item.isDeleted()));
		obj.put(JsonKeys.PRICE, new Double(item.getPrice()));
		obj.put(JsonKeys.TIME_CREATE, new Long(item.getTimeCreate()));
		obj.put(JsonKeys.TIME_EXPIRATION, new Long(item.getTimeExpiration()));
		if (item.getLocation() != null) {
			obj.put(JsonKeys.LOCATION, encodeLocation(item.getLocation()));
		}
		return obj;
	}

	@SuppressWarnings("unchecked")
	private static JSONObject encodeLocation(GeoPoint location) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.LOCATION);
		obj.put(JsonKeys.LATITUDE, new Double(location.getLatitude()));
		obj.put(JsonKeys.LONGITUDE, new Double(location.getLongitude()));
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeItems(final List<EItem> items) {
		JSONObject obj = new JSONObject();
		List<JSONObject> itemObjs = new ArrayList<JSONObject>();
		for (EItem eItem : items) {
			itemObjs.add(encodeItem(eItem));
		}
		obj.put(JsonKeys.TYPE, JsonKeys.ITEM_LIST);
		obj.put(JsonKeys.ITEM_LIST, itemObjs);
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeSearchResult(ItemSearchResult result) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.ITEM_SEARCH_RESULT);
		obj.put(JsonKeys.ITEM, encodeItem(result.getItem()));
		obj.put(JsonKeys.TITLE_SNIPPET, result.getTitleSnippet());
		obj.put(JsonKeys.DESCRIPTION_SNIPPET, result.getDescriptionSnippet());
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeSearchResults(List<ItemSearchResult> results) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.ITEM_SEARCH_RESULT_LIST);
		List<JSONObject> resultObjs = new ArrayList<JSONObject>();
		for (ItemSearchResult result : results) {
			resultObjs.add(encodeSearchResult(result));
		}
		obj.put(JsonKeys.ITEM_SEARCH_RESULT_LIST, resultObjs);
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeSearchResultInfo(
			ItemSearchResultInfo resultInfo) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.ITEM_SEARCH_RESULT_INFO);
		obj.put(JsonKeys.ITEM_SEARCH_RESULT_LIST,
				encodeSearchResults(resultInfo.getResults()));
		obj.put(JsonKeys.COUNT, new Long(resultInfo.getCount()));
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeUser(EUser user) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.USER);
		obj.put(JsonKeys.USER_ID, user.getId());
		obj.put(JsonKeys.USERNAME, user.getUsername());
		obj.put(JsonKeys.GOOGLE_ID, user.getGoogleUserId());
		obj.put(JsonKeys.TIME_CREATE, new Long(user.getTimeCreate()));
		obj.put(JsonKeys.IS_ADMIN, new Boolean(user.isAdmin()));
		obj.put(JsonKeys.IS_ACTIVE, new Boolean(user.isActive()));
		obj.put(JsonKeys.LOCALE, user.getLocale());
		obj.put(JsonKeys.GOOGLE_USER_DATA,encodeGoogleUserData(user.getGoogleUserData()));
		return obj;
	}

	@SuppressWarnings("unchecked")
	private static JSONObject encodeGoogleUserData(EGoogleUserData googleUserData) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.GOOGLE_USER_DATA);
		obj.put(JsonKeys.AUTH_DOMAIN, googleUserData.getAuthDomain());
		obj.put(JsonKeys.EMAIL, googleUserData.getEmail());
		obj.put(JsonKeys.FEDERATED_IDENTITY,
				googleUserData.getFederatedIdentity());
		obj.put(JsonKeys.NICKNAME, googleUserData.getNickname());
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject error() {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.ERROR);
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeFeedbacks(FeedbackData feedbackData) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.FEEDBACKS);
		obj.put(JsonKeys.RATING, new Double(feedbackData.getRatingAverage()));
		obj.put(JsonKeys.ALREADY_RATED,
				new Boolean(feedbackData.isUserAlreadyRated()));
		obj.put(JsonKeys.FEEDBACK_LIST,
				encodeFeedbackList(feedbackData.getItemFeedbackList()));
		return obj;
	}

	@SuppressWarnings("unchecked")
	private static JSONObject encodeFeedbackList(
			List<EItemFeedback> itemFeedbackList) {
		JSONObject obj = new JSONObject();
		List<JSONObject> feedbackObjs = new ArrayList<JSONObject>();
		for (EItemFeedback feedback : itemFeedbackList) {
			feedbackObjs.add(encodeFeedback(feedback));
		}
		obj.put(JsonKeys.TYPE, JsonKeys.FEEDBACK_LIST);
		obj.put(JsonKeys.FEEDBACK_LIST, feedbackObjs);
		return obj;
	}

	@SuppressWarnings("unchecked")
	private static JSONObject encodeFeedback(EItemFeedback feedback) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.FEEDBACK);
		obj.put(JsonKeys.FEEDBACK_ID, feedback.getId());
		obj.put(JsonKeys.FEEDBACK_CONTENT, feedback.getFeedbackContent());
		obj.put(JsonKeys.USER_ID, feedback.getAuthor());
		obj.put(JsonKeys.TIME_CREATE, new Long(feedback.getTimeCreate()));
		switch (feedback.getFeedbackRating()) {
		case NO_RATING:
			obj.put(JsonKeys.RATING, new Integer(0));
			break;
		case RUBY_1:
			obj.put(JsonKeys.RATING, new Integer(1));
			break;
		case RUBY_2:
			obj.put(JsonKeys.RATING, new Integer(2));
			break;
		case RUBY_3:
			obj.put(JsonKeys.RATING, new Integer(3));
			break;
		case RUBY_4:
			obj.put(JsonKeys.RATING, new Integer(4));
			break;
		case RUBY_5:
			obj.put(JsonKeys.RATING, new Integer(5));
			break;
		}
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static JSONObject encodeIds(List<Long> ids) {
		JSONObject obj = new JSONObject();
		obj.put(JsonKeys.TYPE, JsonKeys.ID_LIST);
		obj.put(JsonKeys.ID_LIST, ids);
		return obj;
	}

}
